import 'dart:typed_data';

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';

import 'updater_platform_interface.dart';
import 'entity/download_status.dart';

/// An implementation of [AppUpdaterPlatform] that uses method channels.
class MethodChannelAppUpdater extends AppUpdaterPlatform {
  /// The method channel used to interact with the native platform.
  @visibleForTesting
  final MethodChannel methodChannel =
      const MethodChannel('flutter/app_updater');

  @override
  Future<String?> getPlatformVersion() {
    return methodChannel.invokeMethod<String>('getPlatformVersion');
  }

  @override
  Future<int> enqueueDownload({
    required String url,
    String? localPath,
    Map<String, String>? headers,
    String? title,
    String? description,
  }) {
    return methodChannel.invokeMethod<int>('enqueueDownload', <String, dynamic>{
      'url': url,
      'localPath': localPath,
      'headers': headers,
      'title': title,
      'description': description,
    }).then((int? value) => value!);
  }

  @override
  Future<int> removeDownload(List<int> ids) {
    return methodChannel
        .invokeMethod<int>('removeDownload', ids)
        .then((int? value) => value!);
  }

  @override
  Future<Uri?> getUriForDownloadedFile(int id) {
    return methodChannel
        .invokeMethod<String>('getUriForDownloadedFile', id)
        .then((String? uriString) {
      return uriString != null ? Uri.tryParse(uriString) : null;
    });
  }

  @override
  Future<DownloadStatus?> getDownloadStatus(int id) {
    return methodChannel
        .invokeMethod<Map<dynamic, dynamic>>('getDownloadStatus', id)
        .then((Map<dynamic, dynamic>? status) {
      if (status == null) {
        return null;
      }
      return DownloadStatus.fromJson(status);
    });
  }

  @override
  Future<Uint8List> calculateMD5Checksum(int id) {
    return methodChannel
        .invokeMethod<Uint8List>('calculateMD5Checksum', id)
        .then((Uint8List? value) => value!);
  }

  @override
  Future<void> requestInstallAPK(String uriString) {
    return methodChannel.invokeMethod('requestInstallAPK', uriString);
  }
}
